#ifndef LEVEL_H
#define LEVEL_H

#include "userStates.h"     // Make sure your state is listed in this include.

#include <string>
#include <map>
#include <vector>
#include <list>
#include <sys/stat.h>
#include <fstream>

#include "Vector2df.h"
#include "StringUtility.h"
#include "AnimatedSprite.h"
#include "BackBuffer.h"
#include "Text.h"
#include "Menu.h"
#ifdef _DEBUG
#include "Text.h"
#include "Pixel.h"
#endif

#include "WandorBaseState.h"
#include "BaseUnit.h"
#include "HeroClass.h"
#include "BaseTrigger.h"
#include "StatefulUnit.h"
#include "SpawnUnitData.h"
#include "MapData.h"
#include "BackgroundImage.h"
#include "Hollywood.h"
#include "Decryptor.h"
#include "LevelList.h"

using namespace StringUtility;

class Level : public WandorBaseState
{
    public:
        Level();
        Level(string fileName, string password);
        virtual ~Level();

        virtual void render();
        virtual void pauseScreen(); // pause render
        virtual void update();
        virtual void logicPauseUpdate();
        virtual void pauseUpdate();
        virtual void onPause();
        virtual void onResume();

        virtual void userInput();
        virtual void pauseInput();

        void Activate();
        void LoadLevel(string fileName);
        void LoadLevelFromWString(wstring file);
        void LoadLevelFromWStringVersioned(wstring file);
        void GoToLevel(string levelFileName);
        void GoToLevel(LevelData level);

        MapData* tileMap;
        int GetTileSize() const {return tileMap->getTileSize();};
        SimpleJoy* GetInput() const {return input;};

        string GetFileName() const {return fileName;}
        void SetPassword(string password);
        string getLevelName() const {return levelName;};
        string getAuthor() const {return author;};
        string getDescription() const {return description;};

        Hero* GetHero() {return player;};
        vector< BaseUnit* >* GetFriendlies() {return &friendlies;};
        BaseUnit* GetFriendly(CRuint index) {return friendlies.at(index);};
        int FriendlyCount() const {return friendlies.size();};
        vector< BaseUnit* >* GetEnemies() {return &enemies;};
        BaseUnit* GetEnemy(CRuint index) {return enemies.at(index);};
        int EnemyCount() const {return enemies.size();};
        vector< BaseUnit* >* GetTriggers() {return &triggers;};
        BaseUnit* GetTrigger(CRuint index) {return triggers.at(index);};
        int TriggerCount() const {return triggers.size();};

        void AddUnit(BaseUnit *unit);
        void AddTrigger(BaseUnit *trigger);
        void AddEffect(StatefulUnit *effect);
        StatefulUnit* AddEffect(string effectName, string stateName, const Vector2df p);
        void RemoveEffect(StatefulUnit *effect);
        void RegisterSpawnReset(); // removes all spawned units, checks dead units, sets status if applicable (this registeres the reset to be done in the next update)
        void RegisterSpawnCheck(const SDL_Rect& borders);
        void SpawnUnit(SpawnUnitData* data);
        void RemoveUnit(vector< BaseUnit* >::iterator unit, vector< BaseUnit*>* vec);
        void AddSpawnUnit(SpawnUnitData* data); // inserts a unit in the spawn queue (ordered by spawnPos)

        #ifdef _DEBUG
        string debugText;
        #endif
    protected:
    	void init();
    	bool FileExists(string fileName);
    	bool getLine(wstring temp, wstring& line, uint& currentPos);
		Vector2df GetCenterPosition(Vector2df Pos, Vector2df Size);
		int calculateJumpHeight(CRuint speed);
        bool VecCompare(const Vector2df& v1,const Vector2df& v2); // compares two vectors, returns true if the first should come before the second, false otherwise
        bool IsInRect(const Vector2df& vec, const pair<Vector2df,Vector2df>& rect); // checks whether a vector is in a region spanned by the pair of vectors (top-left and bottom-right corners)
        void ResetSpawn();
        void CheckSpawn(SDL_Rect& borders);

        string fileName;
        string levelName;
        string author;
        string description;
        Decryptor *decryptor;

        Hero* player;
        vector< BaseUnit* > friendlies;
        vector< BaseUnit* > enemies;
        vector< BaseUnit* > triggers;
        list<BackgroundImage*> backgroundImages;
        list<StatefulUnit *> effects; // these will constantly be added and removed, so use a list

        // spawn
        list< SpawnUnitData* > queue;
        bool shouldResetSpawn; // should the spawn queue be reset on the next update?
        SDL_Rect shouldCheckSpawn; // should the spawn queue be checked on next update?

        // pause screen
        BackBuffer pauseBG;
        Text pauseText;
        Menu pauseMenu;

        #ifdef _DEBUG
        Text debugPrint;
        Pixel pix;
        #endif
};

#endif /*LEVEL_H_*/
